package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.ScoreRuleConditionConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.clazz.ConditionClass;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.ItemDataPoJo;
import com.xbongbong.paas.pojo.dto.LinkFormDataDTO;
import com.xbongbong.paas.pojo.vo.LinkFormDataVO;
import com.xbongbong.paas.service.PaasFormDataService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.domain.entity.LabelEntity;
import com.xbongbong.pro.domain.entity.ScoreOperationEntity;
import com.xbongbong.pro.domain.entity.ScoreRangeConditionEntity;
import com.xbongbong.pro.domain.entity.ScoreRangeEntity;
import com.xbongbong.pro.domain.entity.ScoreRuleConditionEntity;
import com.xbongbong.pro.domain.entity.ScoreRuleEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ScoreErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.score.pojo.dto.ScoreFieldConditionDTO;
import com.xbongbong.pro.score.pojo.dto.ScoreRangeSaveDTO;
import com.xbongbong.pro.score.pojo.dto.ScoreRuleSaveDTO;
import com.xbongbong.pro.score.pojo.vo.ScoreFieldConditionVO;
import com.xbongbong.pro.score.pojo.vo.ScoreRangeDetailVO;
import com.xbongbong.pro.score.pojo.vo.ScoreRuleDetailVO;
import com.xbongbong.pro.score.pojo.vo.ScoreRuleSaveVO;
import com.xbongbong.saas.enums.ScoreOperationTypeEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.model.LabelModel;
import com.xbongbong.saas.model.ScoreRuleModel;
import com.xbongbong.saas.service.ScoreRuleService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * 评分业务逻辑封装
 *
 * @author chunyang.qin
 * @version v1.0
 * @date 2020/11/30 17:18
 * @since v1.0
 */
@Component
public class ScoreRuleHelp {

    private static final Logger LOG = LoggerFactory.getLogger(ScoreRuleHelp.class);
    //单个评分规则能够添加的评分字段总数
    private static final Integer MAX_FIELD_COUNT = 20;
    //单个评分字段能够添加的最大条件数
    private static final Integer MAX_FIELD_CONDITION_COUNT = 20;
    //评分条件能够增加/减少的最大分值
    private static final Double MAX_SCORE_OPERATION_VALUE = 99999D;
    //评分条件里面数字类型的最大比较值
    private static final Double MAX_NUM_COMPARE_VALUE = 100000000000D;
    //评分条件里面数字类型的最小比较值
    private static final Double MIN_NUM_COMPARE_VALUE = -100000000000D;
    //评分条件的最大精度
    private static final Integer MAX_NUM_ACCURACY = 6;


    @Resource
    private ScoreRuleModel scoreRuleModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private LabelModel labelModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private PaasFormDataService paasFormDataService;
    @Resource
    private ScoreRuleService scoreRuleService;


    /**
     * 获取该业务对应的评分字段的attr
     * @return
     */
    public String getScoreFieldAttr(Integer businessType) {
        String attr = null;
        if (Objects.nonNull(businessType)) {
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            switch (xbbRefTypeEnum){
                case CUSTOMER_MANAGEMENT:
                    attr = CustomerManagementEnum.SCORE.getAttr();
                    break;
                case CLUE:
                    attr = ClueEnum.SCORE.getAttr();
                    break;
            }
        }
        return attr;
    }

    /**
     * 判断字段，是否是该业务的评分字段
     * eg 客户num_61,线索是 num_1
     *
     * @return
     */
    public Boolean isScoreField(Integer businessType, String attr) {

        if (Objects.nonNull(attr) && Objects.nonNull(businessType)) {
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            switch (xbbRefTypeEnum){
                case CUSTOMER_MANAGEMENT:
                    return Objects.equals(CustomerManagementEnum.SCORE.getAttr(),attr);
                case CLUE:
                    return Objects.equals(ClueEnum.SCORE.getAttr(),attr);
            }
        }
        return false;
    }

    /**
     * 判断字段是否是支持评分字段。
     *
     * @return
     */
    public Boolean isSupportScoreField(Integer businessType, FieldAttrEntity fieldAttrEntity) {
        if (Objects.nonNull(fieldAttrEntity) && Objects.nonNull(businessType)) {
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            return isPortraitScoreField(xbbRefTypeEnum, fieldAttrEntity) || isActionScoreField(xbbRefTypeEnum, fieldAttrEntity);
        }
        return false;
    }

    /**
     * 判断字段是否是画像评分字段。（画像评分里面需要排除“最后跟进时间”）
     *
     * @return
     */
    public Boolean isPortraitScoreField(XbbRefTypeEnum xbbRefTypeEnum, FieldAttrEntity fieldAttrEntity) {
        if (Objects.nonNull(fieldAttrEntity) && Objects.nonNull(xbbRefTypeEnum)) {
            String attr = fieldAttrEntity.getAttr();
            //支持画像评分的字段类型
            boolean contains = listPortraitScoreFieldType().contains(fieldAttrEntity.getFieldType());
            switch (xbbRefTypeEnum) {
                case CUSTOMER_MANAGEMENT:
                    //客户数据： 不属于最后跟进时间，又属于支持评分的字段类型
                    return (!CustomerManagementEnum.LAST_CONNECT_TIME.getAttr().equals(attr)) && contains;
                case CLUE:
                    return (!ClueEnum.LAST_CONNECT_TIME.getAttr().equals(attr)) && contains;
                default:
                    break;
            }
        }
        return false;
    }

    /**
     * 判断字段是否是行为评分字段。
     *
     * @return
     */
    public Boolean isActionScoreField(XbbRefTypeEnum xbbRefTypeEnum, FieldAttrEntity fieldAttrEntity) {
        if (Objects.nonNull(fieldAttrEntity) && Objects.nonNull(xbbRefTypeEnum)) {
            return listActionScoreFieldAttr(xbbRefTypeEnum).contains(fieldAttrEntity.getAttr());
        }
        return false;
    }

    public Boolean haveEnabledScoreRule(String corpid, Long formId) throws XbbException {
        return scoreRuleService.haveEnabledScoreRule(corpid,formId);
    }

    //返回支持画像评分的字段类型 {1(单行文本)，7（多行文本），2(数字)，4（日期），10000（单选按钮），9（复选组框）,3（下拉框）,10001(下拉复选框),800001（标签）}
    public List<Integer> listPortraitScoreFieldType() {
        return Arrays.asList(FieldTypeEnum.TEXT.getType(), FieldTypeEnum.TEXTAREA.getType(), FieldTypeEnum.NUM.getType(), FieldTypeEnum.DATETIME.getType(), FieldTypeEnum.RADIO_GROUP.getType(), FieldTypeEnum.CHECKBOX_GROUP.getType(),
                FieldTypeEnum.COMBO.getType(), FieldTypeEnum.COMBO_CHECK.getType(), FieldTypeEnum.LABEL.getType(), FieldTypeEnum.STAGE_THRUSTER.getType());
    }


    //获取支持行为评分的字段名称{创建时间，最后更新时间}
    public List<String> listActionScoreFieldAttr(XbbRefTypeEnum xbbRefTypeEnum) {
        List<String> fieldAttrList;
        switch (xbbRefTypeEnum) {
            case CUSTOMER_MANAGEMENT:
                fieldAttrList = Arrays.asList(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), CustomerManagementEnum.ADD_TIME.getAttr());
                break;
            case CLUE:
                fieldAttrList = Arrays.asList(ClueEnum.LAST_CONNECT_TIME.getAttr(), ClueEnum.ADD_TIME.getAttr());
                break;
            default:
                fieldAttrList = new ArrayList<>();
                break;
        }
        return fieldAttrList;
    }

    /**
     * 新增，编辑，保存时，把 ScoreRuleSaveDTO 实体类 转为 model 操作的  ScoreRuleEntity
     * 这个方法，新增编辑都是会调用的。要根据 dataId 来处理两种常见的特殊地方
     *
     * @param scoreRuleSaveDTO
     * @return
     */
    public ScoreRuleEntity packageScoreRuleEntity(ScoreRuleSaveDTO scoreRuleSaveDTO) {
        ScoreRuleEntity scoreRuleEntity = new ScoreRuleEntity();
        if (Objects.nonNull(scoreRuleSaveDTO)) {
            Long dataId = scoreRuleSaveDTO.getDataId();
            String corpid = scoreRuleSaveDTO.getCorpid();
            BeanUtil.copyProperties(scoreRuleSaveDTO, scoreRuleEntity);
            if (Objects.nonNull(dataId)) {
                //编辑
                scoreRuleEntity.setId(dataId);
            } else {
                //新增的场景需要给下面的一些属性默认值
                //创建人
                UserVO loginUser = scoreRuleSaveDTO.getLoginUser();
                scoreRuleEntity.setCreatorId(Objects.nonNull(loginUser) ? loginUser.getUserId() : "0");
                //默认不启用
                scoreRuleEntity.setEnable(0);
            }
            //把权重百分比转为小数(前端保存传的是 80，转为0.8存储),保留4位小数
            scoreRuleEntity.setActionScoreRate(new BigDecimal(scoreRuleSaveDTO.getActionScoreRate() * 0.01).setScale(4, RoundingMode.HALF_UP).doubleValue());
            scoreRuleEntity.setPortraitScoreRate(new BigDecimal(scoreRuleSaveDTO.getPortraitScoreRate() * 0.01).setScale(4, RoundingMode.HALF_UP).doubleValue());
            List<ScoreFieldConditionDTO> actionScoreRule = scoreRuleSaveDTO.getActionScoreRule();
            List<ScoreFieldConditionDTO> portraitScoreRule = scoreRuleSaveDTO.getPortraitScoreRule();
            if (CollectionsUtil.isNotEmpty(actionScoreRule)) {
                scoreRuleEntity.setActionScoreRule(JSON.toJSONString(actionScoreRule));
            }
            if (CollectionsUtil.isNotEmpty(portraitScoreRule)) {
                scoreRuleEntity.setPortraitScoreRule(JSON.toJSONString(portraitScoreRule));
            }
        }
        return scoreRuleEntity;
    }

    /**
     * 把model层的 scoreRuleEntity 封装为  ScoreRuleDetailVO
     *
     * @param scoreRuleEntity
     * @return
     * @throws XbbException
     */
    public ScoreRuleDetailVO packageScoreRuleDetailVO(ScoreRuleEntity scoreRuleEntity) throws XbbException {
        ScoreRuleDetailVO scoreRuleDetailVO = new ScoreRuleDetailVO();
        if (Objects.nonNull(scoreRuleEntity)) {
            BeanUtil.copyProperties(scoreRuleEntity, scoreRuleDetailVO);
            List<ScoreFieldConditionVO> acFieldConditionVOS = JSON.parseArray(scoreRuleEntity.getActionScoreRule(), ScoreFieldConditionVO.class);
            List<ScoreFieldConditionVO> proFieldConditionVOS = JSON.parseArray(scoreRuleEntity.getPortraitScoreRule(), ScoreFieldConditionVO.class);
            //评分权重把小数转为百分比的数，给前端(eg：存的是0.8 转为80 给前端)
            scoreRuleDetailVO.setActionScoreRate(scoreRuleEntity.getActionScoreRate() * 100);
            scoreRuleDetailVO.setPortraitScoreRate(scoreRuleEntity.getPortraitScoreRate() * 100);
            //填充  attrName 和  Items 用于前端打开新建，编辑时渲染页面（后端是不需要这两个东西的，只是展示的时候多一步处理）
            List<FieldAttrEntity> formExplain = getFormExplainForRule(scoreRuleEntity);
            fillAttrNameAndItems(scoreRuleEntity, formExplain, acFieldConditionVOS);
            fillAttrNameAndItems(scoreRuleEntity, formExplain, proFieldConditionVOS);
            //组装返回
            scoreRuleDetailVO.setActionScoreRule(acFieldConditionVOS);
            scoreRuleDetailVO.setPortraitScoreRule(proFieldConditionVOS);
        }
        return scoreRuleDetailVO;
    }

    /**
     * 获取评分规则关联的表单的解释
     *
     * @param scoreRuleEntity
     * @return
     * @throws XbbException
     */
    private List<FieldAttrEntity> getFormExplainForRule(ScoreRuleEntity scoreRuleEntity) throws XbbException {
        Long formId = scoreRuleEntity.getFormId();
        String corpid = scoreRuleEntity.getCorpid();
        if (Objects.isNull(formId)) {
            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200013, "表单Id不能为空");
        }
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        if (CollectionsUtil.isEmpty(explainList)) {
            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200013, ScoreErrorCodeEnum.API_ERROR_1200013.getMsg());
        }
        return explainList;
    }

    /**
     * 填充AttrName 和 Items，用于前端回显
     *
     * @param scoreRuleEntity
     * @param explainList
     * @param scoreFieldConditionVOS
     */
    private void fillAttrNameAndItems(ScoreRuleEntity scoreRuleEntity, List<FieldAttrEntity> explainList, List<ScoreFieldConditionVO> scoreFieldConditionVOS) {
        if (CollectionsUtil.isNotEmpty(scoreFieldConditionVOS) && CollectionsUtil.isNotEmpty(explainList)) {
            for (ScoreFieldConditionVO scoreFieldCondition : scoreFieldConditionVOS) {
                FieldAttrEntity filedEntity = explainList.stream().filter(fieldAttrEntity -> fieldAttrEntity.getAttr().equals(scoreFieldCondition.getAttr())).findFirst().get();
                if (Objects.nonNull(filedEntity)) {
                    scoreFieldCondition.setAttrName(filedEntity.getAttrName());
                    //标签的item需要单独查一遍
                    if (FieldTypeEnum.LABEL.getType().equals(filedEntity.getFieldType())) {
                        scoreFieldCondition.setItems(getLabelItems(scoreRuleEntity.getCorpid(), scoreRuleEntity.getFormId()));
                    //阶段涉及多版本也需要再查一遍
                    } else if (Objects.equals(FieldTypeEnum.STAGE_THRUSTER.getType(), filedEntity.getFieldType())) {
                        scoreFieldCondition.setItems(proFormHelp.getEnableStageComboItems(SaasMarkEnum.SAAS.getCode(), scoreRuleEntity.getBusinessType(), scoreRuleEntity.getCorpid(), scoreRuleEntity.getFormId()));
                    } else {
                        scoreFieldCondition.setItems(filedEntity.getItems());
                    }
                }
            }
        }
    }

    /**
     * 查询标签，用于评分条件下拉
     *
     * @param corpid
     * @param formId
     * @return
     */
    private List<ItemPoJo> getLabelItems(String corpid, Long formId) {
        List<ItemPoJo> items = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("formId", formId);
        param.put("del", DelEnum.NORMAL.getDel());
        List<LabelEntity> labelEntities = labelModel.findEntitys(param);
        if (CollectionUtils.isNotEmpty(labelEntities)) {
            ItemPoJo itemPoJo;
            for (LabelEntity labelEntity : labelEntities) {
                itemPoJo = new ItemPoJo();
                itemPoJo.setText(labelEntity.getName());
                itemPoJo.setValue(labelEntity.getId());
                items.add(itemPoJo);
            }
        }
        return items;
    }

    /**
     * 把请求scoreRangeSaveDTO 组装成 model 操作的实体类
     *
     * @param scoreRangeSaveDTO
     * @return
     */
    public ScoreRangeEntity packageScoreRangeEntity(ScoreRangeSaveDTO scoreRangeSaveDTO) {
        ScoreRangeEntity scoreRangeEntity = new ScoreRangeEntity();
        if (Objects.nonNull(scoreRangeSaveDTO)) {
            Long dataId = scoreRangeSaveDTO.getDataId();
            BeanUtil.copyProperties(scoreRangeSaveDTO, scoreRangeEntity);
            if (Objects.nonNull(dataId)) {
                scoreRangeEntity.setId(dataId);
            }
            // 调取 save接口， 只有显示方式选择的是 “range”调用这个方法，所以这边设置为启用
            scoreRangeEntity.setEnable(1);
            List<ScoreRangeConditionEntity> scoreRangeList = scoreRangeSaveDTO.getScoreRangeList();
            if (CollectionsUtil.isNotEmpty(scoreRangeList)) {
                scoreRangeEntity.setData(JSON.toJSONString(scoreRangeList));
            }
        }
        //没有登录的传输 0 ，防止插入creator_Id时失败
        UserVO loginUser = scoreRangeSaveDTO.getLoginUser();
        scoreRangeEntity.setCreatorId(Objects.nonNull(loginUser) ? loginUser.getUserId() : "0");
        return scoreRangeEntity;
    }

    public ScoreRangeDetailVO packageScoreRangeDetailVO(ScoreRangeEntity scoreRangeEntity) {
        ScoreRangeDetailVO scoreRangeDetailVO = new ScoreRangeDetailVO();
        if (Objects.nonNull(scoreRangeEntity)) {
            Long dataId = scoreRangeEntity.getId();
            BeanUtil.copyProperties(scoreRangeEntity, scoreRangeDetailVO);
            if (Objects.nonNull(dataId)) {
                scoreRangeDetailVO.setDataId(dataId);
            }
            String data = scoreRangeEntity.getData();
            if (Objects.nonNull(data)) {
                List<ScoreRangeConditionEntity> scoreRuleConditionEntities = JSON.parseArray(data, ScoreRangeConditionEntity.class);
                if (CollectionsUtil.isNotEmpty(scoreRuleConditionEntities)) {
                    scoreRangeDetailVO.setScoreRangeList(scoreRuleConditionEntities);
                }
            }
        }
        return scoreRangeDetailVO;
    }

    /**
     * 获取评分操作的 加法  减法 操作集合
     *
     * @return
     */
    public List<ScoreOperationEntity> getScoreOperationList() {
        List<ScoreOperationEntity> scoreOperationList = new ArrayList<>();
        ScoreOperationEntity scoreOperationEntity;
        for (ScoreOperationTypeEnum scoreOperationTypeEnum : ScoreOperationTypeEnum.listScoreOperationType()) {
            scoreOperationEntity = new ScoreOperationEntity(scoreOperationTypeEnum.getCode(), scoreOperationTypeEnum.getName(), scoreOperationTypeEnum.getAlias());
            scoreOperationList.add(scoreOperationEntity);
        }
        return scoreOperationList;
    }

    /**
     * 打开新建,编辑评分规则页面,获取解释字段.把处理好的解释 放在  scoreExplainList 中返回
     *
     * @return
     */
    public void setScoreExplainListForSave(ScoreRuleSaveVO scoreRuleSaveVO, String corpid, Long formId, Integer businessType) throws XbbException {
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.THIS_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        //处理掉不能参与评分的字段
        XbbRefTypeEnum xbbRefType = XbbRefTypeEnum.getByCode(businessType);
        List<FieldAttrEntity> scoreExplainList = getScoreExplainList(corpid ,formId, xbbRefType , explainList);
        scoreRuleSaveVO.setPortraitExplainList(getPortraitExplainList(businessType, scoreExplainList));
        scoreRuleSaveVO.setActionExplainList(getActionExplainList(businessType, scoreExplainList));
    }

    /**
     * 获取评分的解释（过滤掉一些不能评分的字段）
     */
    private List<FieldAttrEntity> getScoreExplainList(String corpid, Long formId, XbbRefTypeEnum xbbRefTypeEnum,List<FieldAttrEntity> explainList) throws XbbException {
        List<FieldAttrEntity> scoreExplainList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(explainList)) {
            //退回公海池，分配时间
            String backPublicDateAttr = "";
            String distributionDateAttr = "";
            String scoreAttr = "";
            switch (xbbRefTypeEnum){
                case CUSTOMER_MANAGEMENT:
                    backPublicDateAttr = CustomerManagementEnum.BACK_PUBLIC_DATE.getAttr();
                    distributionDateAttr = CustomerManagementEnum.DISTRIBUTION_DATE.getAttr();
                    scoreAttr = CustomerManagementEnum.SCORE.getAttr();
                    break;
                case CLUE:
                    backPublicDateAttr = ClueEnum.BACK_PUBLIC_DATE.getAttr();
                    distributionDateAttr = ClueEnum.DISTRIBUTION_DATE.getAttr();
                    scoreAttr = ClueEnum.SCORE.getAttr();
            }
            //分配时间字段
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                String attr = fieldAttrEntity.getAttr();
                //去除下面几种字段(1)隐藏字段（eg:关联的客户 id） (2) 禁用字段 (3)设置"不可见"字段
                if (Integer.valueOf(ShowTypeEnum.NONE.getCode()).equals(fieldAttrEntity.getShowType()) || Objects.equals(0,fieldAttrEntity.getIsOpen()) || Objects.equals(0,fieldAttrEntity.getVisible()) ) {
                    continue;
                }
                //客户的"主联系人名称"不能参与评分
                if(Objects.equals(xbbRefTypeEnum,XbbRefTypeEnum.CUSTOMER_MANAGEMENT) && Objects.equals(attr,CustomerManagementEnum.CONTACT_NAME.getAttr())){
                    continue;
                }
                //去除“评分”，"退回公海池","分配时间"字段
                if (Objects.equals(attr,backPublicDateAttr) || Objects.equals(attr,distributionDateAttr) || Objects.equals(attr,scoreAttr)) {
                    continue;
                }
                //标签字段,需要特殊处理 items
                if (FieldTypeEnum.LABEL.getType().equals(fieldAttrEntity.getFieldType())) {
                    fieldAttrEntity.setItems(getLabelItems(corpid, formId));
                }else if(Objects.nonNull(fieldAttrEntity.getLinkForm()) && StringUtil.isNotEmpty(fieldAttrEntity.getLinkForm().getDisplayField())){
                //下拉框关联关联数据
                    LinkFormDataDTO linkFormDataDTO = new LinkFormDataDTO();
                    linkFormDataDTO.setCorpid(corpid);
                    linkFormDataDTO.setAttr(fieldAttrEntity.getAttr());
                    linkFormDataDTO.setFormId(formId);
                    linkFormDataDTO.setLinkForm(fieldAttrEntity.getLinkForm());
                    //设置forScore为1,跳过权限
                    linkFormDataDTO.setForScore(1);
                    LinkFormDataVO linkFormDataVO = paasFormDataService.linkFormData(linkFormDataDTO);
                    if(Objects.nonNull(linkFormDataVO)){
                        List<ItemPoJo> items = new ArrayList<>();
                        ItemPoJo itemPoJo;
                        for(ItemDataPoJo itemDataPoJo : linkFormDataVO.getItems()){
                            itemPoJo = new ItemPoJo();
                            BeanUtil.copyProperties(itemDataPoJo,itemPoJo);
                            items.add(itemPoJo);
                        }
                        fieldAttrEntity.setItems(items);
                    }
                } else{
                    //客户状态，客户阶段。线索状态，线索阶段 items填充
                    List<ItemPoJo> itemPoJos = proFormHelp.getItem(fieldAttrEntity, xbbRefTypeEnum.getCode(), corpid, formId);
                    fieldAttrEntity.setItems(itemPoJos);
                }
                //单选按钮，下拉框 需要过滤掉"其他" RADIO_GROUP
                if(Objects.equals(fieldAttrEntity.getFieldType(),FieldTypeEnum.COMBO.getType()) || Objects.equals(fieldAttrEntity.getFieldType(),FieldTypeEnum.RADIO_GROUP.getType())){
                    List<ItemPoJo> items = fieldAttrEntity.getItems();
                    if(CollectionUtils.isNotEmpty(items)){
                        items.removeIf(item -> Objects.equals(item.getIsOther(),1));
                    }
                }
                scoreExplainList.add(fieldAttrEntity);
            }
        }
        return scoreExplainList;
    }

//    /**
//     * 打开新建评分规则页面,获取解释字段
//     * @return
//     */
//    public void setScoreExplainListForAdd(ScoreRuleAddVO scoreRuleAddVO , String corpid , Long formId , Integer businessType ) throws XbbException {
//        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
//        if(Objects.isNull(paasFormExplainEntity)){
//            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.THIS_EXPLAIN_NOT_EXIST);
//        }
//        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
//        scoreRuleAddVO.setPortraitExplainList(getPortraitExplainList(businessType,explainList));
//        scoreRuleAddVO.setActionExplainList(getActionExplainList(businessType,explainList));
//    }
//
//    /**
//     * 打开编辑评分规则页面,获取解释字段
//     * @return
//     */
//    public void setScoreExplainListForUpdate(ScoreRuleAddVO scoreRuleAddVO , String corpid , Long formId , Integer businessType ) throws XbbException {
//
//        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
//        scoreRuleAddVO.setPortraitExplainList(getPortraitExplainList(businessType,explainList));
//        scoreRuleAddVO.setActionExplainList(getActionExplainList(businessType,explainList));
//    }

    /**
     * 筛选出解释中支持画像评分的字段
     *
     * @param businessType
     * @param explainList
     * @return
     */
    public List<FieldAttrEntity> getPortraitExplainList(Integer businessType, List<FieldAttrEntity> explainList) {
        List<FieldAttrEntity> portraitExplainList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(explainList)) {
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                if (isPortraitScoreField(xbbRefTypeEnum, fieldAttrEntity)) {
                    portraitExplainList.add(fieldAttrEntity);
                }
            }
        }
        return portraitExplainList;
    }

    /**
     * 筛选出解释中属于行为评分的字段
     *
     * @param businessType
     * @param explainList
     * @return
     */
    public List<FieldAttrEntity> getActionExplainList(Integer businessType, List<FieldAttrEntity> explainList) {
        List<FieldAttrEntity> actionExplainList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(explainList)) {
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                if (isActionScoreField(xbbRefTypeEnum, fieldAttrEntity)) {
                    actionExplainList.add(fieldAttrEntity);
                }
            }
        }
        return actionExplainList;
    }

    public void verificationBusinessType(Integer businessType) throws XbbException {
        if (!XbbRefTypeEnum.checkScoreBusinessType(businessType)) {
            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200001, ScoreErrorCodeEnum.API_ERROR_1200001.getMsg());
        }
    }

    /**
     * 保存规则常规校验
     *
     * @param scoreRuleSaveDTO
     * @throws XbbException
     */
    public void verificationData(ScoreRuleSaveDTO scoreRuleSaveDTO) throws XbbException {
        if (Objects.nonNull(scoreRuleSaveDTO)) {
            String corpid = scoreRuleSaveDTO.getCorpid();
            Long formId = scoreRuleSaveDTO.getFormId();
            Integer enable = scoreRuleSaveDTO.getEnable();
            Long dataId = scoreRuleSaveDTO.getDataId();
            String ruleName = scoreRuleSaveDTO.getRuleName();
            Double actionScoreRate = scoreRuleSaveDTO.getActionScoreRate();
            Double portraitScoreRate = scoreRuleSaveDTO.getPortraitScoreRate();
            List<ScoreFieldConditionDTO> actionScoreRule = scoreRuleSaveDTO.getActionScoreRule();
            List<ScoreFieldConditionDTO> portraitScoreRule = scoreRuleSaveDTO.getPortraitScoreRule();

            //校验评分权重介于 0~1 之间
            verificationPositiveInteger(actionScoreRate, portraitScoreRate);
            //校验权重相加等于100%
            verificationRateTotal(actionScoreRate, portraitScoreRate);
            //校验评分字段最多20个
            verificationScoreFieldTotal(actionScoreRule, portraitScoreRule);
            //单个评分条件校验((1)条件总数不超过20个 (2)数字比较值的范围 -100000000000 ~ 100000000000 ,精度最多6位数  (3) 条件加分的分值范围 0 ~ 99999)
            verificationConditionTotal(actionScoreRule);
            verificationConditionTotal(portraitScoreRule);
            //校验最多只有一个启用的表单规则
            List<ScoreRuleEntity> scoreRuleList = getAllScoreRuleByFormId(formId, corpid);
            verificationEnableRuleCount(dataId, enable, scoreRuleList);
            //校验名称是否重复
            verificationRepeatRuleName(dataId, ruleName, scoreRuleList);
        }

    }

    public List<ScoreRuleEntity> getAllScoreRuleByFormId(Long formId, String corpid) {
        Map<String, Object> params = new HashMap<>(4);
        params.put("corpid", corpid);
        params.put("formId", formId);
        params.put("del", 0);
        List<ScoreRuleEntity> scoreRuleList = scoreRuleModel.findEntitys(params);
        return scoreRuleList;
    }

    /**
     * 新增编辑通用校验 只能启用一个规则
     *
     * @param dataId
     * @param enable
     * @param scoreRuleList
     * @throws XbbException
     */
    public void verificationEnableRuleCount(Long dataId, Integer enable, List<ScoreRuleEntity> scoreRuleList) throws XbbException {
        if (CollectionsUtil.isNotEmpty(scoreRuleList)) {
            //enable 为 1 ,表示用户点击的是启用规则,需要校验
            if (Objects.nonNull(enable) && enable > 0) {
                ScoreRuleEntity enableScoreRuleEntity = scoreRuleList.stream().filter(scoreRuleEntity -> Integer.valueOf(1).equals(scoreRuleEntity.getEnable())).findFirst().orElse(null);
                if (Objects.nonNull(enableScoreRuleEntity)) {
                    //dataId为空，表示是新增规则过来的校验
                    if (!enableScoreRuleEntity.getId().equals(dataId)) {
                        throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200014, ScoreErrorCodeEnum.API_ERROR_1200014.getMsg());
                    }
                }
            }
        }
    }

    public void verificationScoreRuleTotal(List<ScoreRuleEntity> scoreRuleList) throws XbbException {
        if (CollectionsUtil.isNotEmpty(scoreRuleList) && scoreRuleList.size() >= 6) {
            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200008, ScoreErrorCodeEnum.API_ERROR_1200008.getMsg());
        }
    }

    /**
     * 新建,编辑校验名称是否重复
     *
     * @param dataId
     * @param ruleName
     * @param scoreRuleList
     * @throws XbbException
     */
    public void verificationRepeatRuleName(Long dataId, String ruleName, List<ScoreRuleEntity> scoreRuleList) throws XbbException {
        if (CollectionsUtil.isNotEmpty(scoreRuleList)) {
            int size = scoreRuleList.size();
            if (dataId != null) {
                //如果是编辑，校验名称重复时，需要排除自己
                for (int index = size - 1; index >= 0; index--) {
                    if (dataId.equals(scoreRuleList.get(index).getId())) {
                        scoreRuleList.remove(index);
                        size--;
                        break;
                    }
                }
            }
            if (size > 0) {
                for (ScoreRuleEntity scoreRuleEntity : scoreRuleList) {
                    if (ruleName.equals(scoreRuleEntity.getRuleName())) {
                        throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200007, ScoreErrorCodeEnum.API_ERROR_1200007.getMsg());
                    }
                }
            }
        }
    }

    //返回支持评分评分的字段类型 {1(单行文本)，7（多行文本），2(数字)，4（日期），10000（单选按钮），9（复选组框）,3（下拉框）,10001(下拉复选框),800001（标签）,10014(创建时间)},更新时间， 注意:最后跟进时间属于日期字段，不是一个单独的字段类型，所以这里没有加
    public static List<ConditionClass> getScoreRuleConditionList(FieldTypeEnum fieldTypeEnum) throws XbbException {
        List<ConditionClass> conditionList = new ArrayList<>();
        try {
            switch (fieldTypeEnum) {
                case DATETIME:
                    String[] datetime = ScoreRuleConditionConstant.DATETIME;
                    conditionList = ConditionEnum.getConditionList(datetime);
                    break;
                case TEXT:
                    String[] text = ScoreRuleConditionConstant.TEXT;
                    conditionList = ConditionEnum.getConditionList(text);
                    break;
                case RADIO_GROUP:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.RADIO_GROUP);
                    break;
                case COMBO:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.COMBO);
                    break;
                case STAGE_THRUSTER:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.STAGE_THRUSTER);
                    break;
                case COMBO_CHECK:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.COMBO_CHECK);
                    break;
                case TEXTAREA:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.TEXTAREA);
                    break;
                case NUM:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.NUM);
                    break;
                case CHECKBOX_GROUP:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.CHECKBOX_GROUP);
                    break;
                case ADDTIME:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.ADDTIME);
                    break;
                case UPDATETIME:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.UPDATETIME);
                    break;
                case LABEL:
                    conditionList = ConditionEnum.getConditionList(ScoreRuleConditionConstant.LABEL);
                    break;
                default:
            }
        } catch (Exception e) {
            LOG.error("condition数据库根据类型获取筛选条件列表出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return conditionList;
    }

    /**
     * 返回评分区间需要的流转条件
     *
     * @param
     * @return
     * @throws XbbException
     */
    public static List<ConditionClass> getScoreRangeConditionList() throws XbbException {
        return ConditionEnum.getConditionList(ScoreRuleConditionConstant.SCORE_RANGE);
    }


    private void verificationPositiveInteger(Double actionScoreRate, Double portraitScoreRate) throws XbbException {
        if (actionScoreRate < 0 || portraitScoreRate < 0 || actionScoreRate > 100 || portraitScoreRate > 100) {
            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200002, ScoreErrorCodeEnum.API_ERROR_1200002.getMsg());
        }
    }

    private void verificationRateTotal(Double actionScoreRate, Double portraitScoreRate) throws XbbException {
        //double比较相等可能会有误差，一般认为偏差在一个较小的范围内则两个数据是相等的
        double mindAccuracyValue = 0.0000001d;
        if ((actionScoreRate + portraitScoreRate) - 100 > mindAccuracyValue) {
            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200003, ScoreErrorCodeEnum.API_ERROR_1200003.getMsg());
        }
    }

    /**
     * 校验评分字段总数是否超过限制
     * @param actionScoreRule
     * @param portraitScoreRule
     * @throws XbbException
     */
    private void verificationScoreFieldTotal(List<ScoreFieldConditionDTO> actionScoreRule, List<ScoreFieldConditionDTO> portraitScoreRule) throws XbbException {
        Integer actionScoreRuleCount = CollectionsUtil.isEmpty(actionScoreRule) ? 0 : actionScoreRule.size();
        Integer portraitScoreRuleCount = CollectionsUtil.isEmpty(portraitScoreRule) ? 0 : portraitScoreRule.size();
        if ((actionScoreRuleCount + portraitScoreRuleCount) > MAX_FIELD_COUNT) {
            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200004, ScoreErrorCodeEnum.API_ERROR_1200004.getMsg());
        }
    }

    private void verificationConditionTotal(List<ScoreFieldConditionDTO> actionScoreRule) throws XbbException {
        List<ScoreRuleConditionEntity> scoreConditionList;
        if (CollectionsUtil.isNotEmpty(actionScoreRule)) {
            for (ScoreFieldConditionDTO scoreFieldConditionDTO : actionScoreRule) {
                verificationScoreConditionTotal(scoreFieldConditionDTO);
            }
        }
    }

    /**
     * 校验单个条件
     * @param scoreFieldConditionDTO
     * @throws XbbException
     */
    private void verificationScoreConditionTotal(ScoreFieldConditionDTO scoreFieldConditionDTO) throws XbbException {
        if (Objects.nonNull(scoreFieldConditionDTO)) {
            String attr = scoreFieldConditionDTO.getAttr();
            Integer fieldType = scoreFieldConditionDTO.getFieldType();
            List<ScoreRuleConditionEntity> scoreConditionList = scoreFieldConditionDTO.getScoreConditionList();
            if(StringUtil.isEmpty(attr) || Objects.isNull(fieldType) || CollectionsUtil.isEmpty(scoreConditionList)){
                throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200021, ScoreErrorCodeEnum.API_ERROR_1200021.getMsg());
            }
            boolean isNum = FieldTypeEnum.NUM.getType().equals(fieldType);
            //条件总数不超过20个
            if (scoreConditionList.size() > MAX_FIELD_CONDITION_COUNT) {
                throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200005, ScoreErrorCodeEnum.API_ERROR_1200005.getMsg());
            }
            for(ScoreRuleConditionEntity scoreRuleConditionEntity : scoreConditionList){
                List<Object> compareValueList = scoreRuleConditionEntity.getValue();
                //条件加分的分值范围 0 ~ 99999
                Double scoreOperationValue = scoreRuleConditionEntity.getScoreOperation().getValue();
                if( scoreOperationValue > MAX_SCORE_OPERATION_VALUE){
                    throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200020, ScoreErrorCodeEnum.API_ERROR_1200020.getMsg());
                }
                //数字比较值的范围 -100000000000 ~ 100000000000  ,精度最多6位数
                if(isNum && CollectionsUtil.isNotEmpty(compareValueList)){
                    List<Object> formatCompareValue = new ArrayList<>(compareValueList.size());
                    for(Object compareValue : compareValueList){
                        if (Objects.isNull(compareValue)) {
                            continue;
                        }
                        double compareDoubleValue = ((Number) compareValue).doubleValue();
                        if(compareDoubleValue > MAX_NUM_COMPARE_VALUE || compareDoubleValue < MIN_NUM_COMPARE_VALUE){
                            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200022, ScoreErrorCodeEnum.API_ERROR_1200022.getMsg());
                        }
                        //四舍五入，精度为6, stripTrailingZeros 去除小数点后多余的0
                        formatCompareValue.add(BigDecimal.valueOf(compareDoubleValue).setScale(MAX_NUM_ACCURACY, RoundingMode.HALF_UP).stripTrailingZeros());
                    }
                    scoreRuleConditionEntity.setValue(formatCompareValue);
                }
            }
        }
    }


}
